// 写自己的VueRouter
// install 传入的参数是vue实例
let _Vue = null
export default class VueRouter {
  static install (Vue) {
    // 1. 判断当前插件是否被安装
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true // 当前插件被安装了
    // 2. vue构造函数记录到全局变量中
    _Vue = Vue
    // 3. 把创建vue实例是传入的router对象注入到所有的vue实例上
    // 混入
    _Vue.mixin({
      beforeCreate () {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router // 这时候的this就指向Vue实例
          this.$options.router.init()
        }
      }
    })
  }

  constructor (options) {
    this.options = options
    this.routerMap = {}
    this.data = _Vue.observable({ // 创建响应式的对象
      current: '/' // 记录当前地址默认是 '/'
    })
  }

  init () {
    this.createRouterMap()
    this.initComponents(_Vue)
    this.initEvent()
  }

  createRouterMap () {
    // 遍历所有的路由规则 然后解析成键值对存储到routerMap里面
    this.options.routes.forEach(route => {
      this.routerMap[route.path] = route.component
    })
  }

  initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      // <router-link to="/blog">Blog</router-link>
      // template: '<a :href="to"><slot></slot></a>'
      render (h) {
        // h函数是vue传递过来的。
        // 接收3个参数
        // 1.一个事选择器
        // 2.可以给设置的dom对象设置属性 耶可以注册事件
        // 3.是生成这个a标签之间的内容 可以有很多内容所有是个数组
        return h('a', {
          attrs: {
            href: '#' + this.to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default]) // 获取默认插槽的内容
      },
      methods: {
        clickHandler (e) {
          window.location.hash = '#' + this.to
          this.$router.data.current = this.to
          e.preventDefault() // 阻止默认行为
        }
      }
    })
    const self = this
    Vue.component('router-view', {
      render (h) {
        // 找到当前路由的地址 再在routerMap找到对应组件
        // h函数会帮我们把这个组件转化为虚拟dom 最终返回
        const component = self.routerMap[self.data.current]
        return h(component)
      }
    })
  }

  initEvent () {
    window.addEventListener('load', this.hashChange.bind(this))
    window.addEventListener('hashchange', this.hashChange.bind(this))
  }

  hashChange () {
    if (!window.location.hash) {
      window.location.hash = '#/'
    }
    this.data.current = window.location.hash.substr(1)
  }
}
